home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcr / pcr4_4.lha / DIST / threads / USpawn.c < prev    next >
C/C++ Source or Header  |  1992-02-18  |  9KB  |  402 lines

  1. /* File: USpawn.c    last edit:
  2.  * Demers        21-May-90 12:38:03
  3.  * Boehm        May 29, 1991 5:12:42 pm PDT
  4.  *
  5.  * Copyright (C) 1990 by Xerox Corporation. All rights reserved.
  6.  *
  7.  * Replacement for system and popen.
  8.  */
  9. /* begincopyright
  10.   Copyright (c) 1988 Xerox Corporation. All rights reserved.
  11.   Use and copying of this software and preparation of derivative works based
  12.   upon this software are permitted. Any distribution of this software or
  13.   derivative works must comply with all applicable United States export
  14.   control laws. This software is made available AS IS, and Xerox Corporation
  15.   makes no warranty about the software, its performance or its conformity to
  16.   any specification. Any person obtaining a copy of this software is requested
  17.   to send their name and post office or electronic mail address to:
  18.     PCR Coordinator
  19.     Xerox PARC
  20.     3333 Coyote Hill Rd.
  21.     Palo Alto, CA
  22.   endcopyright */
  23.  
  24. #include <xr/ThreadsBackdoor.h>
  25. #include <xr/ThreadsMsgPrivate.h>
  26. #include <xr/UIO.h>
  27. #include <xr/UIOPrivate.h>
  28. #include <xr/Errno.h>
  29.  
  30. #include <sys/types.h>
  31. #include <sys/signal.h>
  32. #include <sys/file.h>
  33. #include <sys/ioctl.h>
  34. #include <sys/wait.h>
  35. #include <string.h>
  36. #include <sysexits.h>
  37.  
  38.  
  39. /*
  40.  * The following stuff belongs in a .h file ...
  41.  */
  42.  
  43. #undef iopo_spawnStdin
  44. #undef iopo_spawnStdout
  45. #undef iopo_spawnStderr
  46.  
  47. typedef int (*XR_SpawnConnectProc)(/* XR_Pointer data */);
  48. typedef int (*XR_SpawnExecProc)(/* XR_Pointer data */);
  49.  
  50. #define iopo_spawnExecProc        iopo_args[0]
  51. /* define iopo_spawnWD            iopo_args[1] */
  52. #define iopo_spawnConnectProc        iopo_args[2]
  53. #define iopo_spawnExecClientData    iopo_args[3]
  54. #define iopo_spawnConnectClientData    iopo_args[4]
  55. /* define iopo_spawnPID            iopo_args[5] */
  56.  
  57.  
  58. /*
  59.  * ... end of stuff that belongs in a .h file.
  60.  */
  61.  
  62.  
  63. #define XR_spawnWaitList    (XR_uioArea->uioa_spawnWaitList)
  64.  
  65.  
  66.  
  67. #define XR_SPAWN_DEFAULT_FILE    "/dev/null"
  68. #define XR_SPAWN_IN_OFLAGS    (O_RDONLY)
  69. #define XR_SPAWN_OUT_OFLAGS    (O_WRONLY|O_CREAT|O_TRUNC)
  70.  
  71. #define XR_SPAWN_SHELL_NAME    "sh"
  72. #define XR_SPAWN_SHELL_PATH    "/bin/sh"
  73.  
  74.  
  75.  
  76. #define XR_SPAWN_DEBUG 0
  77.  
  78. #if XR_SPAWN_DEBUG
  79.  
  80. #define CheckSpawnWaitList(m) {\
  81.     if( XR_HeadOfCycleInIOPOList(XR_spawnWaitList) != NIL ) XR_Panic(m); \
  82.     }
  83.  
  84. XR_IOPOrder
  85. XR_HeadOfCycleInIOPOList(list)
  86.     XR_IOPOrder list;
  87. {
  88.     XR_IOPOrder p, t;
  89.     int i;
  90.  
  91.     p = t = list;
  92.     for( i = 0; ; i += 1 ) {
  93.         if( p == NIL ) return NIL;
  94.         p = p->iopo_next;
  95.         if( p == t ) break;
  96.         if( (i & 01) != 0 ) t = t->iopo_next;
  97.     }
  98.     /* given a loop containing p == t find its head */
  99.       /* find its length */
  100.         for( i = 1; t->iopo_next != p; t = t->iopo_next ) i += 1;
  101.       /* find its head */
  102.         p = list;
  103.         while( i > 0 ) { p = p->iopo_next; i -= 1; }
  104.         t = list;
  105.         while( p != t ) { p = p->iopo_next; t = t->iopo_next; }
  106.       return p;
  107. }
  108.  
  109. #else
  110.  
  111. #define CheckSpawnWaitList(m)
  112.  
  113. #endif
  114.  
  115.  
  116. static int
  117. XR_SpawnOpen(name, flags, fd)
  118.     char *name;
  119.     int flags;
  120.     int fd;
  121. {
  122.     int t;
  123.  
  124.     if( (name == NIL) || (name[0] == 0) ) name = XR_SPAWN_DEFAULT_FILE;
  125.     t = open(name, flags, 0666);
  126.     if( t < 0 )
  127.     return( EX_DATAERR );
  128.     if( t != fd ) {
  129.     if( dup2(t, fd) != 0 )
  130.         return( EX_OSERR );
  131.     (void)close(t);
  132.     }
  133.     return(0);
  134. }
  135.  
  136.  
  137. static void
  138. XR_SpawnedChildWorker(
  139.     wd,
  140.     connectProc, connectClientData,
  141.     execProc, execClientData
  142. )
  143.     char *wd;
  144.     XR_SpawnConnectProc connectProc;
  145.     XR_Pointer connectClientData;
  146.     XR_SpawnExecProc execProc;
  147.     XR_Pointer execClientData;
  148. {
  149.     extern char **environ;
  150.     char *(argv[4]);
  151.     int i, ans;
  152.     int zero = 0;
  153.     struct sigvec vec;
  154.  
  155.     (void) chdir( wd ? wd : "/");
  156.  
  157.     for( i = getdtablesize()-1; i >= 0; i-- ) {
  158.     (void)close(i);
  159.     }
  160.  
  161.     vec.sv_handler = SIG_DFL;
  162.     vec.sv_mask = 0;
  163.     vec.sv_flags = 0;
  164.     for( i = 0; i < NSIG; i++ ) {
  165.     (void)sigvec(i, &vec, NIL);
  166.     }
  167.     (void)sigblock(0);
  168.  
  169.     /*
  170.      * The following is supposed to make new pgrp / session id
  171.      *   ready for new control tty in either 4.0.x or 4.1 ...
  172.      */
  173.         if( (i = open("/dev/tty", O_WRONLY, 0)) >= 0 ) {
  174.             (void)ioctl(i, TIOCNOTTY, &zero);
  175.             (void)close(i);
  176.         }
  177.         (void)setpgrp( 0 /*=>self*/, 0 /*=>new*/ );
  178.         /* above equivalent to POSIX / 4.1: (void)setsid(); */
  179.  
  180.     ans = (*connectProc)(connectClientData);
  181.     if( ans != 0 ) exit(ans);
  182.  
  183.     ans = (*execProc)(execClientData);
  184.     exit(ans);
  185. }
  186.  
  187.  
  188. void
  189. XR_SpawnIOPOrderProc (iopo)
  190.     XR_IOPOrder iopo;
  191. /*
  192.     Result in wait->sw_pid is child PID, and wait has been
  193.       linked into waiters list.
  194.     On failure, result in wait->sw_pid is (-errno).
  195. */
  196. {
  197. #   define wd        ((char *)(iopo->iopo_spawnWD))
  198.  
  199. #   define connectProc    \
  200.     ((XR_SpawnConnectProc)(iopo->iopo_spawnConnectProc))
  201. #   define connectClientData    \
  202.     ((XR_Pointer)(iopo->iopo_spawnConnectClientData))
  203.  
  204. #   define execProc    \
  205.     ((XR_SpawnExecProc)(iopo->iopo_spawnExecProc))
  206. #   define execClientData    \
  207.     ((XR_Pointer)(iopo->iopo_spawnExecClientData))
  208.  
  209.     int childID;
  210.  
  211.     if( (childID = fork()) != 0 ) /* parent */ {
  212.     if( childID != -1 ) {
  213.         CheckSpawnWaitList("Check_SpawnIOPOrderProc 0");
  214.         iopo->iopo_spawnPID = childID;
  215.         iopo->iopo_next = XR_spawnWaitList;
  216.         XR_spawnWaitList = iopo;
  217.     } else {
  218.         iopo->iopo_results[0] = -(errno);
  219.         XR_NotifyIOPODone(iopo);
  220.     }
  221.     CheckSpawnWaitList("Check_SpawnIOPOrderProc 1");
  222.     return;
  223.     } else /* child */ {
  224.     XR_SpawnedChildWorker( wd, connectProc, connectClientData,
  225.             execProc, execClientData );
  226.     }
  227.     /*NOTREACHED*/
  228.  
  229. #   undef cmd
  230. #   undef wd
  231. #   undef connectProc
  232. #   undef connectClientData
  233. #   undef execProc
  234. #   undef execClientData
  235. }
  236.  
  237.  
  238.  
  239.  
  240. void
  241. XR_IOPSpawnChildDied()
  242. {
  243.     union wait statusBuf;
  244.     int pid;
  245.     XR_IOPOrder p, prev;
  246.  
  247.     while( (pid = wait3(&statusBuf, WNOHANG, NIL)) > 0 ) {
  248.         p = XR_spawnWaitList; 
  249.         prev = NIL;
  250.         CheckSpawnWaitList("Check_IOPSpawnChildDied");
  251.         while( (p != NIL) && (p->iopo_spawnPID != pid) ) {
  252.         prev = p;
  253.         p = p->iopo_next;
  254.         }
  255.         if( p != NIL ) {
  256.         if( prev == NIL ) {
  257.             XR_spawnWaitList = p->iopo_next;
  258.         } else {
  259.             prev->iopo_next = p->iopo_next;
  260.         }
  261.         p->iopo_results[0] = statusBuf.w_status;
  262.         XR_NotifyIOPODone(p);
  263.         }
  264.     }
  265. }
  266.  
  267.  
  268. #define FixFileName(name) \
  269.     ((name) ? XR_ExpandPath(XR_UIOFixStringArg(name)) : NIL)
  270.  
  271.  
  272. int
  273. XR_CDConnectSpawn(
  274.     wd, connectProc, connectClientData, execProc, execClientData
  275. )
  276.     char *wd;            /* NIL => /, "" => PCR working dir */
  277.     int ((*connectProc)());
  278.     XR_Pointer connectClientData;
  279.     int ((*execProc)());
  280.     XR_Pointer execClientData;
  281. {
  282.     XR_IOPOrder iopo;
  283.     XR_IOPOResult res;
  284.     int status;
  285.  
  286.     iopo = (XR_IOPOrder)(XR_malloc(sizeof(struct XR_IOPOrderRep)));
  287.     XR_InitIOPOrder(iopo);
  288.     iopo->iopo_spawnWD = ((unsigned)(FixFileName(wd)));
  289.     iopo->iopo_spawnConnectProc = ((unsigned)(connectProc));
  290.     iopo->iopo_spawnConnectClientData = ((unsigned)(connectClientData));
  291.     iopo->iopo_spawnExecProc = ((unsigned)(execProc));
  292.     iopo->iopo_spawnExecClientData = ((unsigned)(execClientData));
  293.     iopo->iopo_spawnPID = 0;
  294.     res = XR_IssueIOPOrder(
  295.     /*iop*/        XR_uioArea->uioa_iope,
  296.     /*order*/    iopo,
  297.     /*proc*/    XR_SpawnIOPOrderProc,
  298.     /*cancel*/    NIL,
  299.     /*abortable*/    TRUE,
  300.     /*timeout*/    XR_WAIT_FOREVER
  301.     );
  302.     switch(res) {
  303.     case XR_IOPO_RESULT_OK:
  304.         status = iopo->iopo_results[0];
  305.         if( status < 0 ) {
  306.             XR_SetErrno(-status);
  307.             return(-1);
  308.         }
  309.         return(status);
  310.     case XR_IOPO_RESULT_ABORTED:
  311.         XR_SetErrno(XR_EABORTED);
  312.         return(-1);
  313.     default:
  314.         XR_Panic("XR_Spawn 0");
  315.     }
  316. }
  317.  
  318.  
  319.  
  320. typedef struct XR_SpawnFileNamesRep {
  321.     char *sfn_cmd;
  322.     char *sfn_stdin;
  323.     char *sfn_stdout;
  324.     char *sfn_stderr;
  325. } * XR_SpawnFileNames;
  326.  
  327.  
  328. static int
  329. XR_CDSpawnConnectProc(clientData)
  330.     XR_Pointer clientData;
  331. {
  332.     int ans;
  333.     XR_SpawnFileNames sfn = ((XR_SpawnFileNames)(clientData));
  334.  
  335.     ans = XR_SpawnOpen(sfn->sfn_stdin, XR_SPAWN_IN_OFLAGS, 0);
  336.     if( ans == 0 )
  337.         ans = XR_SpawnOpen(sfn->sfn_stdout, XR_SPAWN_OUT_OFLAGS, 1);
  338.     if( ans == 0 )
  339.         ans = XR_SpawnOpen(sfn->sfn_stderr, XR_SPAWN_OUT_OFLAGS, 2);
  340.     return ans;
  341. }
  342.  
  343.  
  344. static int
  345. XR_CDSpawnExecProc(clientData)
  346.     XR_Pointer clientData;
  347. {
  348.     int ans;
  349.     XR_SpawnFileNames sfn = ((XR_SpawnFileNames)(clientData));
  350.     extern char **environ;
  351.     char *(argv[4]);
  352.  
  353.     argv[0] = XR_SPAWN_SHELL_NAME;
  354.     argv[1] = "-c";
  355.     argv[2] = sfn->sfn_cmd;
  356.     argv[3] = NIL;
  357.  
  358.     (void)execve(XR_SPAWN_SHELL_PATH, argv, environ);
  359.  
  360.     /* if we get here the exec failed */
  361.     return EX_OSERR;
  362. }
  363.  
  364.  
  365. int
  366. XR_CDSpawn(cmd, wd, stdin, stdout, stderr)
  367.     char *cmd;
  368.     char *wd;        /* NIL => /, "" => PCR working dir */
  369.     char *stdin;    /* NIL, "" => /dev/null */
  370.     char *stdout;
  371.     char *stderr;
  372. {
  373.     XR_SpawnFileNames sfn;
  374.  
  375.     sfn = (XR_SpawnFileNames) XR_malloc(sizeof(struct XR_SpawnFileNamesRep));
  376.     sfn->sfn_cmd = XR_UIOFixStringArg(cmd);
  377.     sfn->sfn_stdin = FixFileName(stdin);
  378.     sfn->sfn_stdout = FixFileName(stdout);
  379.     sfn->sfn_stderr = FixFileName(stderr);
  380.     return XR_CDConnectSpawn( wd, XR_CDSpawnConnectProc, sfn,
  381.             XR_CDSpawnExecProc, sfn );
  382. }
  383.  
  384.  
  385. int
  386. XR_Spawn(cmd, stdin, stdout, stderr)
  387.     char *cmd;
  388.     char *stdin;    /* NIL, "" => /dev/null */
  389.     char *stdout;
  390.     char *stderr;
  391. {
  392.     return XR_CDSpawn(cmd, "", stdin, stdout, stderr);
  393. }
  394.  
  395. /* LOG
  396. 21-May-90 12:41:25 - Demers - Created
  397.  
  398.     USpawn.c 1.1 of 5/22/90
  399.     @(#)USpawn.c    1.1
  400. */
  401.  
  402.